package com.company.project.netty;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelId;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import java.util.concurrent.ConcurrentHashMap;

import javax.xml.bind.DatatypeConverter;

/**
 * @author wang
 * @version 1.0.0
 */
@Component
@Qualifier("serverHandler")
@ChannelHandler.Sharable
@Slf4j
public class ServerHandler extends SimpleChannelInboundHandler<byte[]> {

	private static ConcurrentHashMap<Integer,ChannelId> channelMap=new ConcurrentHashMap<Integer, ChannelId>();

	private static ChannelGroup channelGroup=new DefaultChannelGroup ("Channel_Group", GlobalEventExecutor.INSTANCE);
	
	@Override
	public void channelRead0(ChannelHandlerContext ctx, byte[] msg) throws Exception {
		log.info("client msg: " + DatatypeConverter.printHexBinary(msg));
		ChannelId cid=ctx.channel().id();
		channelMap.put(byteArrayToInt(msg), cid);
		
	}

	public static int byteArrayToInt(byte[] msg) {
		int value = 0;
		// 取msg[0]~msg[2]三个字节作为身份标识
		value = msg[2] & 0xFF | (msg[1] & 0xFF) << 8 | (msg[0] & 0xFF) << 16;
		log.info("identity code:" + value);
		return value;
	}

	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {

		log.info("RamoteAddress : " + ctx.channel().remoteAddress() + " active !");
		channelGroup.add(ctx.channel());
		super.channelActive(ctx);
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
		cause.printStackTrace();
		ctx.close();
	}

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		log.info("Channel is disconnected");
		super.channelInactive(ctx);
	}
	
	public static void sendMessage(Integer uid,byte[] msg)  {
		ChannelId cid= channelMap.get(uid);
		if(cid==null) {
			log.error("client "+uid+" is disconnected...");
			return;
		}
		Channel channel= channelGroup.find(cid);
		if(channel==null) {
			log.error("client "+uid+" is disconnected...");
			channelMap.remove(uid);
			return;
		}
		log.info("send message to client "+uid+" "+DatatypeConverter.printHexBinary(msg));
		channel.writeAndFlush(msg);
		
	}
}